{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "14fa7497",
   "metadata": {},
   "source": [
    "# 神经网络入门-MNIST手写数字识别\n",
    "## 简介\n",
    "目前正在学习神经网络的相关知识，决定从MNIST手写数字识别开始入坑神经网络。<br>\n",
    "本项目中记录了我在学习该项目过程中的一点简介以及对于代码的解释，同样入坑的小白可以把本项目作为入坑的开始，项目完全是以小白视角开始的（因为我也是小白），所以对于新手来说（完全不了解神经网络的新手）也能浅入深出地实现神经网络应用的入门。\n",
    "\n",
    "## 本项目要干啥？\n",
    "从“神经网络入门-MNIST手写数字识别”题目来看，本项目就是要实现使用神经网络识别一个手写数字的图片，并准确给出所写的数字。MNIST为数据集名称，是机器学习领域中非常经典的一个数据集，由60000个训练样本和10000个测试样本组成，每个样本都是一张28*28像素的灰度手写数字图片。数据集中需要识别的图片大概长这个样子：\n",
    "\n",
    "<img src=\"https://gitee.com/Anthony_Bridge/assets/raw/master/MNIST/mnist.jpeg\" width=\"600\">\n",
    "\n",
    "\n",
    "## 神经网络是啥？\n",
    "相信大家应该都知道神经网络大概是个什么东西，如果不清除，建议搜索一下“神经网络”或者问问GPT，或者从这一篇博文里面了解一下。https://zhuanlan.zhihu.com/p/377513272\n",
    "\n",
    "## 让我们正式开始学习本项目吧\n",
    "本项目编写的时候，所使用的python版本为3.10.15，需要使用torch，matplotlib，numpy库\n",
    "首先我们引入一些包，这些包都会用到"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "1836b65d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "from torch.utils.data import DataLoader\n",
    "from torchvision import transforms\n",
    "from torchvision import datasets"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af042f60",
   "metadata": {},
   "source": [
    "然后设置一些超参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "1895a9b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 超参数设置\n",
    "batch_size = 64 # 每一批送入的样本数量\n",
    "learning_rate = 0.01 # 学习率\n",
    "momentum = 0.5 # 冲量，对梯度下降法的一种优化\n",
    "EPOCH = 10 # 训练轮数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6c49748",
   "metadata": {},
   "source": [
    "transforms.Compose为设定一套操作顺序，即输入的数据依次进行transforms.ToTensor()和transforms.Normalize((0.1307,), (0.3081,))两个操作。<br>\n",
    "其中transforms.ToTensor()表示将PILImage格式获numpy.array格式数据转化为张量形式，并且该操作会自动将图片中通道值除以255<br>\n",
    "transforms.Normalize对数据进行归一化，第一个参数传入平均值mean，第二个传入标准差std，这里对数据 x = (x - mean)/std，0.1307和0.3081是mnist数据集的均值和标准差，是预先计算的\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "c7186c01",
   "metadata": {},
   "outputs": [],
   "source": [
    "transform = transforms.Compose(\n",
    "    [\n",
    "        transforms.ToTensor(), \n",
    "        transforms.Normalize((0.1307,), (0.3081,))\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9169106a",
   "metadata": {},
   "source": [
    "MNIST已经被包括在torchvision.datasets之中了，所以不需要提前下载到本地，直接在程序中下载就可以"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "02d71dfc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 加载数据集和测试集，加载或下载位置，是否为训练集，是否需要下载，数据变换的处理\n",
    "train_dataset = datasets.MNIST(root='./datasets/MNIST', train=True, download=True, transform=transform)  \n",
    "test_dataset = datasets.MNIST(root='./datasets/MNIST', train=False, download=True, transform=transform)  # train=True训练集，=False测试集\n",
    "# 自动将输入的数据集按照batch_size进行分割，储存为多个张量，shuffle是否表示需要在每个epoch的时候打乱顺序乱序，true表示打乱，默认false\n",
    "train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\n",
    "test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11a191eb",
   "metadata": {},
   "source": [
    "我们先查看数据集中一部分代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "74ed0fe4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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ETl69Kjs27dPatasKSVK+Ox1goAXyP3PF/lkIbZw4UKpU6eOLF68WFwul/v+C5WzKSUl5ZL7fv75Z/ckbXXq1BERkdDQUGnXrl2B2hQXFydxcXEyYsQIWbt2rbRs2VKmTp0qY8eOLdD5THv27BERkUqVKnnlfCicQO6DjRo1kpIlS8qmTZukW7du7vszMzNl69at6j7YEcj9b//+/bJr1y53my72yCOPiIjIyZMnpVy5cgVqJwovkPufL/LJPzlCQkJERMRxHPd9GzZskHXr1uW4/9KlS9Xny999951s2LBB7rrrLhERqVy5srRt21befffdHK8CHD169LJtSUtLk6ysLHVfXFyclChRQn20k5+pA8yPhBzHcXemy/21gOIVyH0wOjpa2rVrJ3PnzpX09HT3/XPmzJHTp09L165dPR6PohfI/W/s2LGyZMkS9W/MmDEiIjJ8+HBZsmSJREZGejwHilYg9z9fZO2K2IwZM+Tzzz+/5P4hQ4ZIQkKCLF68WDp16iQdOnSQvXv3ytSpU6Vhw4Y5zrtVt25dadWqlQwcOFAyMjLkjTfekAoVKsjw4cPd+0yZMkVatWolcXFx0r9/f6lTp4789ttvsm7dOjl48KBs27Ytx3auXr1aBg0aJF27dpX69etLVlaWzJkzR0JCQqRz587u/fL61dnNmzdLjx49pEePHlK3bl05d+6cLFmyRL799lsZMGCANG3aNB+vIgojWPugiMiLL74oLVq0kDZt2siAAQPk4MGDMnHiRGnfvj1LbRWTYO1/rVq1uuS+C1e/rr/+eklMTLzssfCeYO1/IiL//e9/3fOX7dq1S06dOuW+GNK4cWO55557cn39vKq4v6Z54auzl/t34MABJzs72xk3bpwTGxvrhIWFOdddd52zYsUKp0+fPuprphe+Ovvqq686EydOdK688konLCzMad26tbNt27ZLHnv37t1O7969napVqzqhoaFO9erVnYSEBGfhwoXufcyvzu7Zs8fp16+fc9VVVznh4eFO+fLlnVtvvdX58ssv1bnz+tXZPXv2OF27dnVq1arlhIeHO6VLl3aaNWvmTJ061cnOzi7w64q8C/Y+eME333zjtGjRwgkPD3cqVarkPProo05aWlq+X0/kD/3vUkxfUXzof55fgz59+hTkZS0Ul+NcdO0RAAAAxcYnx4gBAAAEAwoxAAAA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q1cvlS8e/yhy6ZiuTz/9VOWmTZuqbM799corr6hsjiG79957L9vWL7/8UuWXX35Z5ZMnT172WBGRrVu3etyeE3/vfyKB9zPQXH80v3MxXnvttSr/9NNPhW5TUaH/+T/zuR8/ftzj/vfcc4/KtucRy60PckUMAADAEgoxAAAASyjEAAAALPGZecSKU0REhMrmmDBzvATziAWekJAQlceMGeO+PWzYMLXtzJkzKj/99NMqm/3DHBPWvHlzlc05mMy1K1NSUlQeOHCgysnJySqbYw9atGih8gMPPOC+3bFjR7Vt1apV4smBAwdUrl27tsf94R+mTp2q8sMPP5yv4wcMGKCyOY4W8Kb4+HjbTShSXBEDAACwhEIMAADAEgoxAAAAS4JyjJi5DhaCjznG5eJxYWfPnlXbzPEzK1euVPmmm25S+cEHH1T5rrvuUtkco2jOWzZz5kyVzXFaprS0NJU///zzy+YePXqobX/96189nnvo0KEet8M/7dy503YT4GMunkuxffv2apu5/u25c+eKtC3mz9BJkyYV6ePZxhUxAAAASyjEAAAALKEQAwAAsCQo15o05yQx1/ozX5Jq1aqpfPTo0aJpWBHx97XWiqL/HTlyROWL13/MyMhQ28zxNJGRkSrXrVs3X489evRolcePH6+yuQ6gv/P3/icSeD8DTT///LPKV111lcf9S5TQf8Ob/wd2797tnYZ5Af0vZ61atVL5ueeec9++44471DZz/sDcxq3mpnz58irffffdKpvrOUdFRXk8nzlmzZwv0Zx7sbix1iQAAICPohADAACwJCinr6hTp47tJsCyX3/9VeWLP5oMCwtT2xo3buzxXOZH219//bXKS5cuVXnfvn0qB9pHkfA/P/74o8q5/Yw0l4WD/zGXWmvUqNFl9x0+fLjK6enphXps86PPpk2bqpzbiKk1a9ao/M4776hs+6PI/OKKGAAAgCUUYgAAAJZQiAEAAFgSlGPEvvnmG5XNr2Iz/iHw3XLLLSonJia6b5vjFX7//XeVZ8yYofLJkydVzszM9EILgeLz3nvvqXzPPfdYagl80cCBA4v18cyfucuXL1d5yJAhKp8/f77I21SUuCIGAABgCYUYAACAJRRiAAAAlgTlGLHt27ernJKSorI5h4653Ie/LXGES5nz4MyZMyfH20Aw+Omnn1TesWOHyldffXVxNgfF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",
      "text/plain": [
       "<Figure size 640x480 with 12 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 显示一部分图片\n",
    "fig = plt.figure()\n",
    "for i in range(12):\n",
    "    plt.subplot(3, 4, i+1)\n",
    "    plt.tight_layout()\n",
    "    plt.imshow(train_dataset.train_data[i], cmap='gray', interpolation='none')\n",
    "    plt.title(\"Labels: {}\".format(train_dataset.train_labels[i]))\n",
    "    plt.xticks([])\n",
    "    plt.yticks([])\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4aa41995",
   "metadata": {},
   "source": [
    "这里能看到先显示了MNIST数据集中的部分图片和标签。<br>\n",
    "下面，我们正式开始搭建我们的神经网络，网络的代码如下。<br>\n",
    "在这里我们需要关注的其实只是__init__函数中的self.conv1，self.conv2，self.fc<br>\n",
    "\n",
    "self.conv1和self.conv2分别表示第一个和第二个卷积层，self.fc表示全连接层，输入的数据会依次经过两个卷积层和一个全连接层输出<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "e2623efc",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(torch.nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        # 该例子中，输入的是一个单通道的图像, 高宽均为28，维度为batch*1*28*28\n",
    "        self.conv1 = torch.nn.Sequential(\n",
    "            # 通道数从1->10,维度为 batch*10*(height - (kernel_size1 - 1))*(weight - (kernel_size1 - 1))\n",
    "            # 在该例子中，经过Conv2d卷积之后，维度变为了 batch*10*24*24\n",
    "            torch.nn.Conv2d(1, 10, kernel_size=5), \n",
    "            torch.nn.ReLU(), # 激活函数\n",
    "            # 在该例子中，经过池化后，维度变成了 batch*10*12*12\n",
    "            torch.nn.MaxPool2d(kernel_size=2), # 通道数不变，高宽变为一半，维度为 batch*10*((height - (kernel_size1 - 1))/2)*((weight - (kernel_size1 - 1)/2)\n",
    "        )\n",
    "        self.conv2 = torch.nn.Sequential(\n",
    "            # 通道数从10->20，维度 batch*20*((height - (kernel_size1 - 1))/2) - (kernel_size2 - 1)*((weight - (kernel_size1 - 1))/2) - (kernel_size2 - 1)\n",
    "            # 在该例子中，再次经过卷积后，维度变成了 batch*20*8*8\n",
    "            torch.nn.Conv2d(10, 20, kernel_size=5),\n",
    "            torch.nn.ReLU(), # 激活函数\n",
    "            # 通道数不变，高宽再变为一半，维度为 batch*20*(((height - (kernel_size1 - 1))/2) - (kernel_size2 - 1))/2*(((weight - (kernel_size1 - 1))/2) - (kernel_size2 - 1))/2\n",
    "            # 在该例子中，再次经过池化后，维度变成了 batch*20*4*4\n",
    "            torch.nn.MaxPool2d(kernel_size=2), \n",
    "        )\n",
    "        self.fc = torch.nn.Sequential(\n",
    "            # 这一步输入的维度为(batch,320)，经过下面两步后，维度变成(batch,10)\n",
    "            torch.nn.Linear(320, 50),\n",
    "            torch.nn.Linear(50, 10),\n",
    "        )\n",
    "        \n",
    "    def forward(self, x):\n",
    "        batch_size = x.size(0)\n",
    "        # 一层卷积层,一层池化层,一层激活层(图是先卷积后激活再池化，差别不大)\n",
    "        x = self.conv1(x)\n",
    "        # 再来一次\n",
    "        x = self.conv2(x)\n",
    "        # view函数的操作是把矩阵自动变换为某个维度，比如view(x,y)这里将矩阵自动变换为x*y，-1表示自适应\n",
    "        # flatten 变成全连接网络需要的输入 (batch,20,4,4) ==> (batch,320), 因为经过卷积之后维度为batch*20*4*4\n",
    "        # 所以这里-1自适应为320,并且，矩阵维度降低到2维\n",
    "        x = x.view(batch_size, -1)\n",
    "        # 获取输出\n",
    "        x = self.fc(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "b67a29e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = Net()\n",
    "criterion = torch.nn.CrossEntropyLoss()  # 交叉熵损失\n",
    "# 随机梯度下降法，momentum冲量0-1之间，>0的时候，算法会考虑之前的梯度，有利于收敛\n",
    "# lr 学习率，每次更新的步长，如果太大会震荡，太小收敛慢\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate, momentum=momentum)  # lr学习率，momentum冲量"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "106b6dd4",
   "metadata": {},
   "source": [
    "训练代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "0ab4b4c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 训练\n",
    "def train(epoch):\n",
    "    running_loss = 0.0\n",
    "    running_total = 0\n",
    "    running_correct = 0\n",
    "    \n",
    "    # batch_idx获取索引，data具体的数据，0表示索引从0开始\n",
    "    for batch_idx, data in enumerate(train_loader, 0):\n",
    "        inputs, target = data\n",
    "        # 梯度归零\n",
    "        optimizer.zero_grad()\n",
    "        # 这一步调用了nn.Module中的__call__ : Callable[..., Any] = _call_impl\n",
    "        # 执行_call_impl函数，会依次执行forward_pre_hook,forward,forward_hook,backward_hook多个函数\n",
    "        # 其中包括forward，并且这里不能直接写model.forward\n",
    "        # 这里返回了一个2维张量，维度为batch*10，共有10列，每一列代表归属某一类的预测得分\n",
    "        outputs = model(inputs)\n",
    "        # 计算损失，返回的结果是标量(0维张量)\n",
    "        loss = criterion(outputs, target)\n",
    "        # 反向传播，反向遍历计算图，链式法则完成，获得每个参数的梯度值\n",
    "        loss.backward()\n",
    "        # 通过梯度下降更新参数\n",
    "        optimizer.step()\n",
    "        # item表示获取具体的数值\n",
    "        running_loss += loss.item()\n",
    "        # dim=1表示输出所在行的最大值，dim=0表示输出所在列的最大值\n",
    "        # outputs.data表示获取输出张量的原始数据（即张量本身），不涉及梯度，但是在新版本的torch中，可以直接使用outputs，.data操作已经给过时\n",
    "        _, predicted = torch.max(outputs.data, dim = 1)\n",
    "        # 总预测数量，输入张量的行的数量，这里感觉是batch_size\n",
    "        running_total += inputs.shape[0]\n",
    "        # 预测正确的数量和\n",
    "        running_correct += (predicted == target).sum().item()\n",
    "        \n",
    "        # 每300次计算一次平均损失和准确率\n",
    "        if batch_idx % 300 == 299:\n",
    "            print('[%d, %5d]: loss: %.3f , acc: %.2f %%'\n",
    "                  % (epoch + 1, batch_idx + 1, running_loss / 300, 100 * running_correct / running_total))\n",
    "            running_loss = 0.0\n",
    "            running_total = 0\n",
    "            running_correct = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4f3f1d79",
   "metadata": {},
   "source": [
    "测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "09c5ae95",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试\n",
    "def test():\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    # 不用计算梯度\n",
    "    # with语句表示在运行过程中不管是否异常都执行清理操作，释放资源\n",
    "    with torch.no_grad():\n",
    "        for data in test_loader:\n",
    "            images, labels = data\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs.data, dim=1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "    acc = correct / total\n",
    "    print('[%d / %d]: Accuracy on test set: %.1f %% ' % (epoch+1, EPOCH, 100 * acc))  # 求测试的准确率，正确数/总数\n",
    "    return acc\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ed40f83",
   "metadata": {},
   "source": [
    "主函数，运行后自动开始训练，并在完成后显示训练结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "f141cf7a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1,   300]: loss: 0.803 , acc: 76.48 %\n",
      "[1,   600]: loss: 0.212 , acc: 93.87 %\n",
      "[1,   900]: loss: 0.149 , acc: 95.47 %\n",
      "[1 / 10]: Accuracy on test set: 95.9 % \n",
      "[2,   300]: loss: 0.124 , acc: 96.19 %\n",
      "[2,   600]: loss: 0.103 , acc: 96.86 %\n",
      "[2,   900]: loss: 0.095 , acc: 97.28 %\n",
      "[2 / 10]: Accuracy on test set: 97.4 % \n",
      "[3,   300]: loss: 0.086 , acc: 97.35 %\n",
      "[3,   600]: loss: 0.082 , acc: 97.50 %\n",
      "[3,   900]: loss: 0.077 , acc: 97.55 %\n",
      "[3 / 10]: Accuracy on test set: 98.2 % \n",
      "[4,   300]: loss: 0.070 , acc: 97.79 %\n",
      "[4,   600]: loss: 0.067 , acc: 97.97 %\n",
      "[4,   900]: loss: 0.067 , acc: 97.89 %\n",
      "[4 / 10]: Accuracy on test set: 98.4 % \n",
      "[5,   300]: loss: 0.060 , acc: 98.22 %\n",
      "[5,   600]: loss: 0.059 , acc: 98.15 %\n",
      "[5,   900]: loss: 0.058 , acc: 98.21 %\n",
      "[5 / 10]: Accuracy on test set: 97.6 % \n",
      "[6,   300]: loss: 0.050 , acc: 98.44 %\n",
      "[6,   600]: loss: 0.051 , acc: 98.50 %\n",
      "[6,   900]: loss: 0.057 , acc: 98.33 %\n",
      "[6 / 10]: Accuracy on test set: 98.5 % \n",
      "[7,   300]: loss: 0.048 , acc: 98.58 %\n",
      "[7,   600]: loss: 0.050 , acc: 98.59 %\n",
      "[7,   900]: loss: 0.045 , acc: 98.61 %\n",
      "[7 / 10]: Accuracy on test set: 98.6 % \n",
      "[8,   300]: loss: 0.040 , acc: 98.68 %\n",
      "[8,   600]: loss: 0.044 , acc: 98.63 %\n",
      "[8,   900]: loss: 0.046 , acc: 98.60 %\n",
      "[8 / 10]: Accuracy on test set: 98.7 % \n",
      "[9,   300]: loss: 0.036 , acc: 98.86 %\n",
      "[9,   600]: loss: 0.042 , acc: 98.68 %\n",
      "[9,   900]: loss: 0.043 , acc: 98.62 %\n",
      "[9 / 10]: Accuracy on test set: 98.6 % \n",
      "[10,   300]: loss: 0.040 , acc: 98.82 %\n",
      "[10,   600]: loss: 0.034 , acc: 98.94 %\n",
      "[10,   900]: loss: 0.038 , acc: 98.90 %\n",
      "[10 / 10]: Accuracy on test set: 98.9 % \n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 主函数\n",
    "if __name__ == \"__main__\":\n",
    "    acc_list_test = []\n",
    "    for epoch in range(0, EPOCH):\n",
    "        train(epoch)\n",
    "        acc_test = test()\n",
    "        acc_list_test.append(acc_test)\n",
    "    plt.plot(acc_list_test)\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Accuracy On TestSet')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b587c34",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "rocm_torch",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
